package middleware

import (
	"fmt"
	"net/http"
	"path/filepath"
	"strings"

	"github.com/gin-gonic/gin"
)

// UploadConfig 上传配置
type UploadConfig struct {
	MaxFileSize    int64
	AllowedTypes   []string
	MaxFileNameLen int
}

// UploadValidation 上传验证中间件
func UploadValidation(config UploadConfig) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 检查是否是multipart/form-data请求
		if !strings.Contains(c.Request.Header.Get("Content-Type"), "multipart/form-data") {
			c.JSON(http.StatusUnsupportedMediaType, gin.H{
				"code":    http.StatusUnsupportedMediaType,
				"message": "请求类型必须为multipart/form-data",
			})
			c.Abort()
			return
		}

		// 对于分片上传，验证参数
		if c.Request.URL.Path == "/upload/part" {
			uploadID := c.PostForm("upload_id")
			partNumber := c.PostForm("part_number")
			fileKey := c.PostForm("file_key")

			if uploadID == "" || partNumber == "" || fileKey == "" {
				c.JSON(http.StatusBadRequest, gin.H{
					"code":    http.StatusBadRequest,
					"message": "缺少分片上传必要参数",
				})
				c.Abort()
				return
			}

			c.Next()
			return
		}

		// 对于完整上传，验证文件
		file, err := c.FormFile("file")
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"code":    http.StatusBadRequest,
				"message": fmt.Sprintf("获取文件失败: %v", err),
			})
			c.Abort()
			return
		}

		// 验证文件名长度
		if config.MaxFileNameLen > 0 && len(file.Filename) > config.MaxFileNameLen {
			c.JSON(http.StatusBadRequest, gin.H{
				"code":    http.StatusBadRequest,
				"message": fmt.Sprintf("文件名长度不能超过%d个字符", config.MaxFileNameLen),
			})
			c.Abort()
			return
		}

		// 验证文件大小
		if config.MaxFileSize > 0 && file.Size > config.MaxFileSize {
			c.JSON(http.StatusBadRequest, gin.H{
				"code":    http.StatusBadRequest,
				"message": fmt.Sprintf("文件大小不能超过%d字节", config.MaxFileSize),
			})
			c.Abort()
			return
		}

		// 验证文件类型
		if len(config.AllowedTypes) > 0 {
			fileExt := strings.ToLower(filepath.Ext(file.Filename))
			if fileExt == "" {
				c.JSON(http.StatusBadRequest, gin.H{
					"code":    http.StatusBadRequest,
					"message": "文件没有扩展名",
				})
				c.Abort()
				return
			}

			// 移除点号
			fileExt = fileExt[1:]

			allowed := false
			for _, t := range config.AllowedTypes {
				if t == fileExt {
					allowed = true
					break
				}
			}

			if !allowed {
				c.JSON(http.StatusBadRequest, gin.H{
					"code":    http.StatusBadRequest,
					"message": fmt.Sprintf("不支持的文件类型，允许的类型: %s", strings.Join(config.AllowedTypes, ",")),
				})
				c.Abort()
				return
			}
		}

		c.Next()
	}
}
